
#include "Gameplay/Board.h"
#include "Gameplay/Piece.h"

namespace Gameplay {

Board::Board(unsigned int w, unsigned int h) :
	width(w),
	height(h),
	fixedPieces(w,0),
	givenPieces(w,0),
	piecesLeft(w*h)
 {
}

// Instantiates a new piece that is able to fit in the stacked pieces

Board::~Board(){
}

bool Board::fit(const Piece & piece) {
	int pieceRow = (piece.pieceID & 0x0000ff00) >> 8;
	int pieceColumn = (piece.pieceID & 0x000000ff);
	if (pieceRow == piece.row && pieceColumn == piece.column) {
		fixedPieces[pieceColumn]++;
		return true;
	}
	return false;
}

// Gives a new ID for a new piece
Sint32 Board::nextPiece() {
  	// So podemos retornar a mesma peca se estivermos
	// na ultima coluna do jogo. Caso contrario devemos
	// retornar sempre uma peca diferente da ultima.
	if (piecesLeft <= 0) return -1;
	int pieceRow, pieceColumn;
	do {
		pieceColumn = rand() % width;
		pieceRow = height-givenPieces[pieceColumn]-1;
	} while ((pieceRow < 0));
	givenPieces[pieceColumn]++;
	piecesLeft--;
 	return ((pieceRow << 8) | pieceColumn);
}

bool Board::canMove(const Piece & piece, Misc::Direction direction) {
  	switch (direction) {
		case Misc::DIRECTION_DOWN: 
			/* TODO: check if there are pieces down */
			if ((piece.row >= this->height-1) || (this->height - piece.row - 1 <= fixedPieces[piece.column])) {
				return false;
			}
			break;
		
		case Misc::DIRECTION_LEFT:
			return ((piece.column > 0) && (this->height - piece.row + 1 > fixedPieces[piece.column-1]));
			break;
		case Misc::DIRECTION_RIGHT:
			return ((piece.column < this->width -1) && (this->height - piece.row + 1 > fixedPieces[piece.column+1]));
			break;
		default:
			break;
	}
	return true;
}


} // namespace Gameplay
